/**
 * 
 */
package controller.xml;

import model.NoSuchDirectoryException;
import model.preprocessor.EPreProcessor;
import model.preprocessor.PreProcessorFactory;
import model.preprocessor.PreProcessorParameter;
import model.solver.SolverFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

import controller.preprocessor.PreProcessor;

/**
 * Use to parse a {@link PreProcessor} in the exported session in XML.
 * 
 * @author GRONOWSKI Stephane svan001@aol.com
 * 
 *         igsat 2010
 * 
 */
public class PreProcessorXMLHandler extends XMLHandler {

	private PreProcessor			preproc			= null;
	private PreProcessorXMLStatus	status			= PreProcessorXMLStatus.NONE;
	private boolean					alreadyParam	= false;
	private PreProcessorFactory		factory;

	/**
	 * Create a handler for xml parsing.
	 * 
	 * @param factory
	 *            a {@link SolverFactory}
	 */
	public PreProcessorXMLHandler(PreProcessorFactory factory) {
		this.factory = factory;
	}

	@Override
	public boolean characters2(char[] ch, int start, int length) throws SAXException {

		switch (status) {
		case NONE:
		case PARAMETER:
			throw new SAXException("not supposed to receive character in this status");
		default:
			return super.characters2(ch, start, length);
		}
	}

	@Override
	public boolean endDocument2() throws SAXException {
		return false;
	}

	@Override
	public boolean endElement2(String uri, String localName, String qName) throws SAXException {
		switch (status) {
		case NONE:
			return false;

		case PARAMETER:
			if (qName.equals(XMLBaliseFormat.PARAMETER))
			{// ferme parameter
				status = PreProcessorXMLStatus.NONE;
				PreProcessorParameter param = null;
				switch (preproc.getType()) {
				case HYPRE:
					param = ((HypreParameterXMLHandlers) delegate).getParam();
					break;
				case REVIVAL:
					param = ((RevivalParameterXMLHandler) delegate).getParam();
					break;
				case SATELLITE_1_0:
					param = ((SatelliteParameterXMLHandler) delegate).getParam();
					break;
				default:
				}
				if (param != null)
					preproc.setPreprocParameter(param);
				else
					throw new SAXException("problem parameter");

				delegate = null;
				return true;
			}
			throw new SAXException("end of PARAMETER was expected");

		case TYPE:
			if (qName.equals(XMLBaliseFormat.PREPROC_TYPE))
			{// ferme TYPE
				setType();
				status = PreProcessorXMLStatus.NONE;
				return true;
			}
			throw new SAXException("end of TYPE was expected");
		}

		// attend une fin de balise qui existe pas...
		throw new SAXException("an other end of element was expected");
	}

	@Override
	public boolean startElement2(String arg0, String arg1, String arg2, Attributes arg3) throws SAXException {
		if (status != PreProcessorXMLStatus.NONE)
			throw new SAXException("already have a started element");

		if (arg2.equals(XMLBaliseFormat.PARAMETER))
		{// balise parameter
			if (arg3.getLength() != 1)
				throw new SAXException("problem attribute for PARAMETER");
			String at = arg3.getValue(XMLBaliseFormat.TYPE_PARAMETER);
			if (!at.equals(XMLBaliseFormat.TYPE_PARAMETER_PREPROCESSOR))
				throw new SAXException("bad attribute for PARAMETER");

			if (alreadyParam)
				throw new SAXException("already have a PARAMETER");

			// set les donne pour recupere le parameter
			status = PreProcessorXMLStatus.PARAMETER;
			switch (preproc.getType()) {
			case HYPRE:
				delegate = new HypreParameterXMLHandlers();
				break;
			case SATELLITE_1_0:
				delegate = new SatelliteParameterXMLHandler();
				break;
			case REVIVAL:
				delegate = new RevivalParameterXMLHandler();
				break;
			default:
				throw new SAXException("problem solver type");
			}
			return true;
		}

		if (arg2.equals(XMLBaliseFormat.PREPROC_TYPE))
		{// balise type
			if (preproc != null)
				throw new SAXException("already have a PREPROC");

			status = PreProcessorXMLStatus.TYPE;
			return true;
		}
		// peut pas commencer balise qui existe pas
		throw new SAXException("unexpected balise: " + arg2);
	}

	/**
	 * Return the {@link PreProcessor}.
	 * 
	 * @return the PreProcessor
	 */
	public PreProcessor getPreproc() {
		return preproc;
	}

	/**
	 * Set the type and create the {@link PreProcessor}.
	 * 
	 * @throws SAXException
	 */
	private void setType() throws SAXException {
		EPreProcessor type = EPreProcessor.getValueFromXML(buffer.toString());
		try
		{
			preproc = factory.createPreProcessor(type);
		} catch (NoSuchDirectoryException e)
		{
			e.printStackTrace();
			throw new SAXException("pb creating preproc");
		}
		if (preproc == null)
			throw new SAXException("unidentified preproc");
	}


}
